from __future__ import annotations

"""
重启自愈服务
------------
进程启动时对账未完成的决策，避免重复下单
"""

import logging
from typing import List

from sqlalchemy import select, and_
from sqlalchemy.ext.asyncio import AsyncSession

from ..models import Decision, DecisionStatus, TradingOrder
from ..services.reconciler import reconcile_orders

logger = logging.getLogger(__name__)


async def recover_pending_decisions(
    session: AsyncSession,
    run_id: str,
) -> int:
    """恢复未完成的决策：先对账，再决定是否继续执行
    
    流程：
    1. 查询所有 EXECUTING/APPROVED 状态的决策
    2. 对每个决策，检查是否已有对应的订单
    3. 如果有订单，标记为 EXECUTED
    4. 如果没有订单且状态为 EXECUTING，标记为 ERROR（可能已失败）
    5. 如果没有订单且状态为 APPROVED，可以继续执行（但建议人工确认）
    """
    # 1. 查询未完成的决策
    stmt = select(Decision).where(
        and_(
            Decision.run_id == run_id,
            Decision.status.in_([DecisionStatus.EXECUTING, DecisionStatus.APPROVED])
        )
    ).order_by(Decision.ts.desc())
    
    result = await session.execute(stmt)
    pending_decisions = result.scalars().all()
    
    if not pending_decisions:
        logger.info(f"没有待恢复的决策: run_id={run_id}")
        return 0
    
    logger.info(f"发现 {len(pending_decisions)} 个待恢复决策: run_id={run_id}")
    
    recovered_count = 0
    
    # 2. 对账订单
    # 先执行一次对账，确保订单状态最新
    await reconcile_orders(session, exchange=None)
    
    # 3. 检查每个决策
    for decision in pending_decisions:
        action_json = decision.action_json
        action = action_json.get("action")
        
        if action == "NOP":
            decision.status = DecisionStatus.EXECUTED
            decision.result = {"status": "skipped", "reason": "NOP action"}
            await session.commit()
            recovered_count += 1
            continue
        
        # 检查是否已有对应的订单
        if action == "OPEN":
            # 查找可能的订单（通过 client_order_id 或决策参数）
            # 由于我们使用预插入，应该能通过决策 ID 或时间窗口找到订单
            stmt = select(TradingOrder).where(
                and_(
                    TradingOrder.run_id == run_id,
                    TradingOrder.exchange == action_json.get("exchange"),
                    TradingOrder.symbol == action_json.get("symbol"),
                    TradingOrder.side == action_json.get("side"),
                )
            ).order_by(TradingOrder.created_at.desc()).limit(5)
            
            result = await session.execute(stmt)
            possible_orders = result.scalars().all()
            
            # 检查时间窗口（决策时间前后 5 分钟）
            from datetime import timedelta
            time_window_start = decision.ts - timedelta(minutes=5)
            time_window_end = decision.ts + timedelta(minutes=5)
            
            matching_order = None
            for order in possible_orders:
                if time_window_start <= order.created_at <= time_window_end:
                    # 检查金额是否匹配（允许一定误差）
                    decision_amount = float(action_json.get("amount", 0))
                    order_amount = float(order.amount)
                    if abs(decision_amount - order_amount) / max(decision_amount, 0.001) < 0.01:  # 1% 误差
                        matching_order = order
                        break
            
            if matching_order:
                # 找到匹配的订单，标记为已执行
                decision.status = DecisionStatus.EXECUTED
                decision.result = {
                    "order_id": matching_order.order_id,
                    "client_order_id": matching_order.client_order_id,
                    "status": "recovered"
                }
                await session.commit()
                logger.info(f"恢复决策: decision_id={decision.id}, order_id={matching_order.order_id}")
                recovered_count += 1
                continue
            else:
                # 没找到订单
                if decision.status == DecisionStatus.EXECUTING:
                    # EXECUTING 状态但没有订单，可能执行失败
                    decision.status = DecisionStatus.ERROR
                    decision.reason = "重启恢复：未找到对应订单，可能执行失败"
                    await session.commit()
                    logger.warning(f"决策可能执行失败: decision_id={decision.id}")
                else:
                    # APPROVED 状态，可以继续执行（但建议记录）
                    logger.info(f"决策待执行: decision_id={decision.id}, status={decision.status}")
    
    logger.info(f"恢复完成: 处理了 {recovered_count} 个决策")
    return recovered_count

